#include "stdafx.h"
#include "Light.h"
#include "..\..\Global\globaldef.h"

/**
Constructor
*/
tLight::tLight() {

	m_Type = 0;
	m_Position = D3DXVECTOR3(0,0,0);
	m_Diffuse = D3DXVECTOR3(0,0,0);
	m_Brightness = 0.0f;
	ZeroMemory(&m_Name, sizeof(tCharBuffer));
}

/**
	Enables external updating of the transformation applied to this light. Updates via this 
	function are immediatly reflected in the subsequently rendered frame
	
	@author Dacre Denny
	@param pTransform pointer to the transformation data being applied to the light instance
*/
void tLight::UpdateTransform(tMatrix4 *pTransform) {

	if(pTransform) {

		m_Position.x = pTransform->m41;
		m_Position.y = pTransform->m42;
		m_Position.z = pTransform->m43;
	}
}

/**
The function assumes the the passed shader has already been bound to the device for rendering
and immediatly binds the light's data to specified fields within the passed shader

@param pShader the shader object to which parameters of the material will be bound
@param lightIndex the index of the light in the shader
@return true if successful otherwise false
*/
bool tLight::ApplyToShader(const Render::tShader *pShader, const uint lightIndex) {

	try {

		if(!pShader)
			throw tException();
		
		char symbolBuffer[128] = {0};
		char structBuffer[64] = {0};
		char fieldBuffer[64] = {0};
		#define SET_SHADER_SCALAR_PARAMETER(field, data) \
			sprintf(symbolBuffer, "%s@%s", structBuffer, field); \
			Render::Singleton()->SetShaderFloat(symbolBuffer, data);
		#define SET_SHADER_VECTOR_PARAMETER(field, data) \
			sprintf(symbolBuffer, "%s@%s", structBuffer, field); \
			Render::Singleton()->SetShaderVector(symbolBuffer, data);

		sprintf(structBuffer, "OmniLight[%i]",lightIndex);

		SET_SHADER_VECTOR_PARAMETER("aux", &D3DXVECTOR4(m_Position.x, m_Position.y, m_Position.z, 0.0f));
		SET_SHADER_VECTOR_PARAMETER("color", &D3DXVECTOR4(m_Diffuse.x, m_Diffuse.y, m_Diffuse.z, 0.0f));
		SET_SHADER_SCALAR_PARAMETER("diffuse", m_DiffuseScale);
		SET_SHADER_SCALAR_PARAMETER("specular", m_SpecularScale);
		SET_SHADER_SCALAR_PARAMETER("brightness", m_Brightness);
	
		return true;
	}
	catch(tException e) {

		std::string message;
		tException::GetMessage(&e, message);
		return false;
	}
}

/**
Constructor
*/
tDirectLight::tDirectLight() : tLight() {

	m_Type = 1;
	m_Direction = D3DXVECTOR3(0,0,0);
}

/**
	Enables external updating of the transformation applied to this light. Updates via this 
	function are immediatly reflected in the subsequently rendered frame
	
	@author Dacre Denny
	@param pTransform pointer to the transformation data being applied to the light instance
*/
void tDirectLight::UpdateTransform(tMatrix4 *pTransform) {

	if(pTransform) {

		/*m_Position.x = pTransform->m41;
		m_Position.y = pTransform->m42;
		m_Position.z = pTransform->m43;*/
		
		m_Direction.x = pTransform->m31;
		m_Direction.y = pTransform->m32;
		m_Direction.z = pTransform->m33;
		D3DXVec3Normalize(&m_Direction,&m_Direction);
		printf("[%f %f %f]\n", m_Direction.x, m_Direction.y, m_Direction.z);
	}
}

/**
The function assumes the the passed shader has already been bound to the device for rendering
and immediatly binds the directional light's data to specified fields within the passed shader

@param pShader the shader object to which parameters of the material will be bound
@param lightIndex the index of the light in the shader
@return true if successful otherwise false
*/
bool tDirectLight::ApplyToShader(const Render::tShader *pShader, const uint lightIndex) {

	try {

		if(!pShader)
			throw tException();
		
		char symbolBuffer[128] = {0};
		char structBuffer[64] = {0};
		char fieldBuffer[64] = {0};
		#define SET_SHADER_SCALAR_PARAMETER(field, data) \
			sprintf(symbolBuffer, "%s@%s", structBuffer, field); \
			Render::Singleton()->SetShaderFloat(symbolBuffer, data);
		#define SET_SHADER_VECTOR_PARAMETER(field, data) \
			sprintf(symbolBuffer, "%s@%s", structBuffer, field); \
			Render::Singleton()->SetShaderVector(symbolBuffer, data);

		sprintf(structBuffer, "DirectLight[%i]",lightIndex);

		SET_SHADER_VECTOR_PARAMETER("aux", &D3DXVECTOR4(m_Direction.x, m_Direction.y, m_Direction.z, 0.0f));
		SET_SHADER_VECTOR_PARAMETER("color", &D3DXVECTOR4(m_Diffuse.x, m_Diffuse.y, m_Diffuse.z, 0.0f));
		SET_SHADER_SCALAR_PARAMETER("diffuse", m_DiffuseScale);
		SET_SHADER_SCALAR_PARAMETER("specular", m_SpecularScale);
		SET_SHADER_SCALAR_PARAMETER("brightness", m_Brightness);
	
		return true;
	}
	catch(tException e) {

		std::string message;
		tException::GetMessage(&e, message);
		return false;
	}
}
